﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Threading;
using QXGameEngine.Logic;
using System.Windows.Media.Imaging;
using System.Xml.Linq;

namespace QXGameEngine.Control {
    public partial class QXSpirit : UserControl {

        public DispatcherTimer Timer { get; set; }
        /// <summary>
        /// 精灵控件
        /// </summary>
        public QXSpirit() {
            InitializeComponent();
            Timer = new DispatcherTimer();
            Timer.Interval = TimeSpan.FromMilliseconds(400);
            Timer.Tick += new EventHandler(Timer_Tick);
            Timer.Start();
        }

        #region 身份属性

        /// <summary>
        /// 获取或设置头像代号
        /// </summary>
        public int FaceSign { get; set; }

        /// <summary>
        /// 获取或设置PK模式
        /// </summary>
        public PKModes PKMode { get; set; }

        /// <summary>
        /// 获取或设置门派名
        /// </summary>
        public string VFaction {
            get { return Faction.Text; }
            set { Faction.Text = value; }
        }

        /// <summary>
        /// 获取或设置家族名
        /// </summary>
        public string VClan {
            get { return Clan.Text; }
            set { Clan.Text = value; }
        }

        /// <summary>
        /// 获取或设置姓名
        /// </summary>
        public string VSName {
            get { return SName.Text; }
            set { SName.Text = value; }
        }

        #endregion

        #region 基本值属性

        /// <summary>
        /// 获取或设置等级
        /// </summary>
        public int VLevel { get; set; }

        /// <summary>
        /// 获取或设置自身的经验值(如果为怪物等NPC,则为杀它的玩家可以得到的经验值)
        /// </summary>
        public int VExperience { get; set; }

        /// <summary>
        /// 获取或设置下一级所需要经验值
        /// </summary>
        public int VLevelUpExperience { get; set; }

        /// <summary>
        /// PK值(正值代表善良,负值代表邪恶, 正负7之间)
        /// </summary>
        public int VPK { get; set; }

        /// <summary>
        /// 获取最大负重
        /// </summary>
        public double VBurdenMax {
            get { return ABase[0] + Equip[0] + Buff[0] + VPower * Coefficient[0]; }
        }

        /// <summary>
        /// 获取物理攻击力最小值
        /// </summary>
        public double VAttackMin {
            get { return ABase[1] + Equip[1] + Buff[1] + VPower * Coefficient[1]; }
        }

        /// <summary>
        /// 获取物理攻击力最大值
        /// </summary>
        public double VAttackMax {
            get { return ABase[2] + Equip[2] + Buff[2] + VPower * Coefficient[2]; }
        }

        /// <summary>
        /// 获取命中值
        /// </summary>
        public double VHit {
            get { return ABase[3] + Equip[3] + Buff[3] + VAgile * Coefficient[3]; }
        }

        /// <summary>
        /// 获取闪避值
        /// </summary>
        public double VDodge {
            get { return ABase[4] + Equip[4] + Buff[4] + VAgile * Coefficient[4]; }
        }

        /// <summary>
        /// 获取跑步速度(每移动一个单元格的花费时间,越小越快)
        /// </summary>
        public double VRunSpeed {
            get { return ABase[5] + Equip[5] + Buff[5] - VAgile * Coefficient[5]; }
        }

        /// <summary>
        /// 获取物攻速度(越小越快)
        /// </summary>
        public double VAttackSpeed {
            get { return ABase[6] + Equip[6] + Buff[6] - VAgile * Coefficient[6]; }
        }

        /// <summary>
        /// 获取施法速度(越小越快)
        /// </summary>
        public double VMagicSpeed {
            get { return ABase[7] + Equip[7] + Buff[7] - VAgile * Coefficient[7]; }
        }

        /// <summary>
        /// 获取或设置当前生命值
        /// </summary>
        public double VLife { get; set; }

        /// <summary>
        /// 获取最大生命值
        /// </summary>
        public double VLifeMax {
            get { return ABase[8] + Equip[8] + Buff[8] + VPhysique * Coefficient[8]; }
        }

        /// <summary>
        /// 获取物理防御力
        /// </summary>
        public double VDefense {
            get { return ABase[9] + Equip[9] + Buff[9] + VPhysique * Coefficient[9]; }
        }

        /// <summary>
        /// 获取格档率
        /// </summary>
        public double VBlock {
            get { return ABase[10] + Equip[10] + Buff[10] + VPhysique * Coefficient[10]; }
        }

        /// <summary>
        /// 获取或设置当前魔法值
        /// </summary>
        public double VSpell { get; set; }

        /// <summary>
        /// 获取最大魔法值
        /// </summary>
        public double VSpellMax {
            get { return ABase[11] + Equip[11] + Buff[11] + VWisdom * Coefficient[11]; }
        }

        /// <summary>
        /// 获取魔法防御力
        /// </summary>
        public double VMagicDefense {
            get { return ABase[12] + Equip[12] + Buff[12] + VWisdom * Coefficient[12]; }
        }

        /// <summary>
        /// 获取魔法攻击力最小值
        /// </summary>
        public double VMagicMin {
            get { return ABase[13] + Equip[13] + Buff[13] + VWisdom * Coefficient[13]; }
        }

        /// <summary>
        /// 获取魔法攻击力最大值
        /// </summary>
        public double VMagicMax {
            get { return ABase[14] + Equip[14] + Buff[14] + VWisdom * Coefficient[14]; }
        }

        /// <summary>
        /// 获取暴击率
        /// </summary>
        public double VBurst {
            get { return ABase[15] + Equip[15] + Buff[15] + VLucky * Coefficient[15]; }
        }

        /// <summary>
        /// 获取或设置当前活力值
        /// </summary>
        public double VEnergy { get; set; }

        /// <summary>
        /// 获取或设置最大活力值
        /// </summary>
        public double VEnergyMax { get; set; }

        /// <summary>
        /// 获取或设置属性基数
        /// 0-14对应基础属性值
        /// </summary>
        public double[] ABase { get; set; }

        /// <summary>
        /// 获取或设置装备加成总和
        /// 0-14对应基础属性值
        /// 15-19对应5大属性
        /// </summary>
        public double[] Equip { get; set; }

        /// <summary>
        /// 获取或设置加持/减持值总和
        /// 0-14对应基础属性值
        /// 15-19对应5大属性
        /// </summary>
        public double[] Buff { get; set; }

        /// <summary>
        /// 获取或设置属性系数(成长率)
        /// 0-14对应基础属性值
        /// </summary>
        public double[] Coefficient { get; set; }

        double _VPower;
        /// <summary>
        /// 获取或设置力量
        /// 影响最大负重,物理攻击力(最小 - 最大)
        /// --[相关基值属性计算公式]:
        /// 最大负重 = ABase[0] + Equip[0] + Buff[0] + VPower * Coefficient[0]
        /// 物理攻击力最小值 = ABase[1] + Equip[1] + Buff[1] + VPower * Coefficient[1]
        /// 物理攻击力最大值 = ABase[2] + Equip[2] + Buff[2] + VPower * Coefficient[2]
        /// </summary>
        public double VPower {
            get { return _VPower + Equip[16] + Buff[16]; }
            set { _VPower = value; }
        }

        double _VAgile;
        /// <summary>
        /// 获取或设置敏捷
        /// 影响命中,闪避,跑速,攻速,施法速度
        /// --[相关基值属性计算公式]:
        /// 命中 = ABase[3] + Equip[3] + Buff[3] + VAgile * Coefficient[3]
        /// 闪避 = ABase[4] + Equip[4] + Buff[4] + VAgile * Coefficient[4]
        /// 跑速 = ABase[5] - Equip[5] + Buff[5] - VAgile * Coefficient[5]
        /// 物攻速度 = ABase[6] - Equip[6] + Buff[6] - VAgile * Coefficient[6]
        /// 施法速度 = ABase[7] - Equip[7] + Buff[7] - VAgile * Coefficient[7]
        /// </summary>
        public double VAgile {
            get { return _VAgile + Equip[17] + Buff[17]; }
            set { _VAgile = value; }
        }

        double _VPhysique;
        /// <summary>
        /// 获取或设置体格
        /// 影响最大生命值,物理防御力,格档率(与暴击率相反,物理或魔法攻击伤害减半)
        /// --[相关基值属性计算公式]:
        /// 最大生命值 = ABase[8] + Equip[8] + Buff[8] + VPhysique * Coefficient[8]
        /// 物理防御力 = ABase[9] + Equip[9] + Buff[9] + VPhysique * Coefficient[9]
        /// 格档率 = ABase[10] + Equip[10] + Buff[10] + VPhysique * Coefficient[10]
        /// </summary>
        public double VPhysique {
            get { return _VPhysique + Equip[18] + Buff[18]; }
            set { _VPhysique = value; }
        }

        double _VWisdom;
        /// <summary>
        /// 获取或设置智慧
        /// 影响最大魔法值,魔法防御力,魔法攻击力(最小 - 最大)
        /// --[相关基值属性计算公式]:
        /// 最大魔法值 = ABase[11] + Equip[11] + Buff[11] + VWisdom * Coefficient[11]
        /// 魔法防御力 = ABase[12] + Equip[12] + Buff[12] + VWisdom * Coefficient[12]
        /// 魔法攻击力最小值 = ABase[13] + Equip[13] + Buff[13] + VWisdom * Coefficient[13]
        /// 魔法攻击力最大值 = ABase[14] + Equip[14] + Buff[14] + VWisdom * Coefficient[14]
        /// </summary>
        public double VWisdom {
            get { return _VWisdom + Equip[19] + Buff[19]; }
            set { _VWisdom = value; }
        }

        double _VLucky;
        /// <summary>
        /// 获取或设置幸运
        /// 影响暴击率(物理或魔法攻击加倍)及其他
        /// --[相关基值属性计算公式]:
        /// 暴击率 = ABase[15] + Equip[15] + Buff[15] + VLucky * ACoefficient[15]
        /// </summary>
        public double VLucky {
            get { return _VLucky + Equip[20] + Buff[20]; }
            set { _VLucky = value; }
        }

        #endregion

        #region 界面属性

        /// <summary>
        /// 设置精灵阴影
        /// </summary>
        public bool ShadowVisible {
            set { BodyShadow.BlurRadius = value ? 7 : 0; }
        }

        /// <summary>
        /// 3个身份描述与画布顶部的距离
        /// </summary>
        public double DescribtionTop {
            get { return (double)Describtion.GetValue(Canvas.TopProperty); }
            set { Describtion.SetValue(Canvas.TopProperty, value); }
        }

        /// <summary>
        /// 获取或设置精灵身体高度
        /// </summary>
        public double BodyHeight {
            get { return Body.Height; }
            set { Body.Height = value; }
        }

        /// <summary>
        /// 设置门派名颜色笔刷
        /// </summary>
        public Brush FactionBrush {
            set { Faction.Foreground = value; }
        }

        /// <summary>
        /// 设置家族名颜色笔刷
        /// </summary>
        public Brush ClanBrush {
            set { Clan.Foreground = value; }
        }

        /// <summary>
        /// 设置姓名颜色笔刷
        /// </summary>
        public Brush SNameBrush {
            set { SName.Foreground = value; }
        }

        /// <summary>
        /// 设置头顶生命值条颜色笔刷
        /// </summary>
        public Brush LifeBrush {
            set { Life.Fill = value; }
        }

        /// <summary>
        /// 获取或设置头顶生命值条当前宽度
        /// </summary>
        public double LifeWidth {
            get { return Life.Width; }
            set { if (LifeWidth != value) { Life.Width = value; } }
        }

        /// <summary>
        /// 获取或设置头顶生命值条满值宽度
        /// </summary>
        public double LifeTotalWidth {
            get { return LifePanel.Width; }
            set { LifePanel.Width = value; LifeBorder.Width = value; }
        }

        /// <summary>
        /// 获取或设置锁定的目标精灵对象
        /// </summary>
        public string LockObject { get; set; }

        /// <summary>
        /// 获取或设置精灵单位图片左上角点与精灵图片中角色脚底的X距离
        /// </summary>
        public double CenterX { get; set; }

        /// <summary>
        /// 获取或设置精灵单位图片左上角点与精灵图片中角色脚底的Y距离
        /// </summary>
        public double CenterY { get; set; }

        /// <summary>
        /// 获取或设置精灵X坐标(关联属性)
        /// </summary>
        public double X {
            get { return (double)GetValue(XProperty); }
            set { SetValue(XProperty, value); }
        }
        public static readonly DependencyProperty XProperty = DependencyProperty.Register(
            "X",
            typeof(double),
            typeof(QXSpirit),
            new PropertyMetadata(ChangeXProperty)
        );
        private static void ChangeXProperty(DependencyObject d, DependencyPropertyChangedEventArgs e) {
            QXSpirit spirit = (QXSpirit)d;
            if (spirit.Visibility == Visibility.Visible) {
                spirit.SetValue(Canvas.LeftProperty, (double)e.NewValue - spirit.CenterX);
            }
        }

        /// <summary>
        /// 获取或设置精灵Y坐标(关联属性)
        /// </summary>
        public double Y {
            get { return (double)GetValue(YProperty); }
            set { SetValue(YProperty, value); }
        }
        public static readonly DependencyProperty YProperty = DependencyProperty.Register(
            "Y",
            typeof(double),
            typeof(QXSpirit),
            new PropertyMetadata(ChangeYProperty)
        );
        private static void ChangeYProperty(DependencyObject d, DependencyPropertyChangedEventArgs e) {
            QXSpirit spirit = (QXSpirit)d;
            if (spirit.Visibility == Visibility.Visible) {
                spirit.SetValue(Canvas.TopProperty, (double)e.NewValue - spirit.CenterY);
                spirit.SetValue(Canvas.ZIndexProperty, Convert.ToInt32(e.NewValue));
            }
        }

        /// <summary>
        /// 获取或设置精灵当前朝向:0朝上4朝下,顺时针依次为0,1,2,3,4,5,6,7(关联属性)
        /// </summary>
        public double Direction {
            get { return (double)GetValue(DirectionProperty); }
            set { SetValue(DirectionProperty, value); }
        }
        public static readonly DependencyProperty DirectionProperty = DependencyProperty.Register(
            "Direction",
            typeof(double),
            typeof(QXSpirit),
            null
        );

        /// <summary>
        /// 获取父容器
        /// </summary>
        public Canvas ParentCanvas {
            get { return this.Parent as Canvas; }
        }

        /// <summary>
        /// 获取或设置精灵图片宽
        /// </summary>
        public double Width_ {
            get { return Body.Width; }
            set { Body.Width = value; Describtion.Width = value; }
        }

        /// <summary>
        /// 获取或设置精灵图片高
        /// </summary>
        public double Height_ {
            get { return Body.Height; }
            set { Body.Height = value; }
        }

        #endregion

        #region 控件属性

        /// <summary>
        /// 获取或设置脚底示为障碍物区域扩展宽度
        /// </summary>
        public int HoldWidth { get; set; }

        /// <summary>
        /// 获取或设置脚底示为障碍物区域扩展高度
        /// </summary>
        public int HoldHeight { get; set; }

        /// <summary>
        /// 获取或设置物理攻击范围(距离)
        /// </summary>
        public int AttackRange { get; set; }

        /// <summary>
        /// 获取或设置索敌范围(距离)
        /// </summary>
        public int SeekRange { get; set; }

        /// <summary>
        /// 获取或设置精灵图片实体部分(共4个部分x1-x2,y1-y2)
        /// </summary>
        public double[] EfficaciousSection { get; set; }

        Actions _Action;
        /// <summary>
        /// 获取或设置精灵当前动作
        /// </summary>
        public Actions Action {
            get { return _Action; }
            set { if (_Action != value) { _Action = value; ChangeAction(); } }
        }

        /// <summary>
        /// 获取或设置精灵类型
        /// </summary>
        public SpiritTypes Type { get; set; }

        /// <summary>
        /// 获取或设置精灵各动作对应的帧列范围(暂时只有5个动作)
        /// </summary>
        public int[] EachActionFrameRange { get; set; }

        /// <summary>
        /// 获取或设置精灵单张图片宽
        /// </summary>
        public int SingleWidth { get; set; }

        /// <summary>
        /// 获取或设置精灵单张图片高
        /// </summary>
        public int SingleHeight { get; set; }

        /// <summary>
        /// 获取或设置精灵移动目的地
        /// </summary>
        public Point Destination { get; set; }

        /// <summary>
        /// 获取或设置精灵的魔法攻击目标坐标
        /// </summary>
        public Point MagicTarget { get; set; }

        /// <summary>
        /// 是否启用了A*移动
        /// </summary>
        public bool UseAStarMove { get; set; }

        /// <summary>
        /// 获取或设置是否为移动后施法过程
        /// </summary>
        public bool IsMagicMove { get; set; }

        /// <summary>
        /// 获取或设置精灵当前准备或右键魔法相关参数
        /// [0],代号
        /// [1],等级
        /// </summary>
        public int[] MagicArgs { get; set; }

        /// <summary>
        /// 施法距离
        /// </summary>
        public int MagicRange { get; set; }

        /// <summary>
        /// 获取或设置精灵衣服代码
        /// </summary>
        public int EquipmentBody { get; set; }

        /// <summary>
        /// 获取或设置精灵武器代码
        /// </summary>
        public int EquipmentWeapon { get; set; }

        /// <summary>
        /// 获取或设置帧推进器
        /// </summary>
        public int FrameCounter { get; set; }

        /// <summary>
        /// 获取或设置精灵当前动作开始图片列号
        /// </summary>
        public int CurrentStartFrame { get; set; }

        /// <summary>
        /// 获取或设置精灵当前动作结束图片列号
        /// </summary>
        public int CurrentEndFrame { get; set; }

        /// <summary>
        /// 获取或设置各动作产生实际效果的针序号
        /// </summary>
        public int[] EffectiveFrame { get; set; }

        /// <summary>
        /// 获取或设置死亡延迟计数
        /// </summary>
        public int DeathDelay { get; set; }

        /// <summary>
        /// 获取或设置精灵生命线程的刷新率
        /// </summary>
        public TimeSpan RefreshRate {
            get { return Timer.Interval; }
            set { Timer.Interval = value; }
        }

        #endregion

        #region 方法与事件

        /// <summary>
        /// 精灵线程间隔事件
        /// </summary>
        private void Timer_Tick(object sender, EventArgs e) {
            //动态更改精灵图片源以形成精灵连续动作
            Body.Source = EquipmentWeapon == -1
                ? Super.getImage(string.Format(@"/Image/Role/Body/{0}/{1}-{2}.png", EquipmentBody, (int)Direction, FrameCounter))
                : Super.ComposeEquip(
                    string.Format(@"/Image/Role/Body/{0}/{1}-{2}.png", EquipmentBody, (int)Direction, FrameCounter),
                    string.Format(@"/Image/Role/Weapon/{0}/{1}-{2}.png", EquipmentWeapon, (int)Direction, FrameCounter),
                    SingleWidth,
                    SingleHeight,
                    50);
            //如果触动起效帧
            if (FrameCounter == EffectiveFrame[(int)Action]) {
                switch (Action) {
                    case Actions.Attack:
                        Super.DoInjure(this);
                        if (this.Name == "Leader") {
                            MainPage.GameMedia.Source = new Uri(@"/Audio/sword.mp3", UriKind.Relative);
                            MainPage.GameMedia.Play();
                        }
                        break;
                    case Actions.Magic:
                        Super.LoadXElement(string.Format("Magic{0}", MagicArgs[0].ToString()), Super.GetXElement(Super.Settings["Arguments"], "Magic", "Code", MagicArgs[0].ToString()));
                        XElement magicData = Super.Settings[string.Format("Magic{0}", MagicArgs[0].ToString())];
                        XElement magicValue = Super.GetXElement(magicData, "Level", "Value", MagicArgs[1].ToString());
                        int consumption = Convert.ToInt32(magicValue.Attribute("Consumption").Value);
                        //只有魔力值足够才能放魔法
                        if (VSpell < consumption) {
                            Super.ShowText(this, FontWeights.Bold, FontStyles.Italic, "魔法值不足", 24, Colors.Green);
                        } else {
                            VSpell -= consumption;
                            QXMagic magic = new QXMagic() {
                                MagicOwner = this.Name,
                                CurrentEndFrame = (int)magicData.Attribute("FrameNum") - 1,
                                EffectiveFrame = (int)magicData.Attribute("EffectiveFrame"),
                                Code = MagicArgs[0],
                                Direction = (bool)magicData.Attribute("HasDirection") ? (int)Direction : 0,
                                Radius = (int)magicData.Attribute("Radius"),
                                CenterX = (double)magicData.Attribute("CenterX"),
                                CenterY = (double)magicData.Attribute("CenterY"),
                                X = MagicTarget.X,
                                Y = MagicTarget.Y,
                                ATK = Convert.ToInt32(magicValue.Attribute("ATK").Value),
                                Consumption = consumption,
                            };
                            (this.Parent as Canvas).Children.Add(magic);
                        }
                        if (this.Name == "Leader") {
                            MainPage.GameMedia.Source = new Uri(@"/Audio/magic.mp3", UriKind.Relative);
                            MainPage.GameMedia.Play();
                        }
                        break;
                    case Actions.Death:
                        Timer.Stop();
                        Timer.Tick -= Timer_Tick;
                        Timer = null;
                        break;
                }
            }
            if (Action == Actions.Magic && FrameCounter == CurrentEndFrame) {
                //放完魔法停止
                IsMagicMove = false;
                Action = Actions.Stop;
            }
            FrameCounter = FrameCounter == CurrentEndFrame ? CurrentStartFrame : FrameCounter + 1;
        }

        /// <summary>
        /// 改变精灵动作状态后激发的属性及线程改变
        /// </summary>
        private void ChangeAction() {
            switch (Action) {
                case Actions.Stop:
                    RefreshThread(400, 0, EachActionFrameRange[0] - 1);
                    break;
                case Actions.Run:
                    RefreshThread(VRunSpeed, EachActionFrameRange[0], EachActionFrameRange[0] + EachActionFrameRange[1] - 1);
                    break;
                case Actions.Attack:
                    RefreshThread(VAttackSpeed, EachActionFrameRange[0] + EachActionFrameRange[1], EachActionFrameRange[0] + EachActionFrameRange[1] + EachActionFrameRange[2] - 1);
                    break;
                case Actions.Magic:
                    RefreshThread(VMagicSpeed, EachActionFrameRange[0] + EachActionFrameRange[1] + EachActionFrameRange[2], EachActionFrameRange[0] + EachActionFrameRange[1] + EachActionFrameRange[2] + EachActionFrameRange[3] - 1);
                    break;
                case Actions.Death:
                    RefreshThread(300, EachActionFrameRange[0] + EachActionFrameRange[1] + EachActionFrameRange[2] + EachActionFrameRange[3], EachActionFrameRange[0] + EachActionFrameRange[1] + EachActionFrameRange[2] + EachActionFrameRange[3] + EachActionFrameRange[4] - 1);
                    break;
            }
            FrameCounter = CurrentStartFrame;
        }

        /// <summary>
        /// 刷新精灵线程参数
        /// </summary>
        /// <param name="timeSpan">动作图片切换间隔</param>
        /// <param name="startFrame">动作在合成大图中的开始列</param>
        /// <param name="endFrame">动作在合成大图中的结束列</param>
        private void RefreshThread(double timeSpan, int startFrame, int endFrame) {
            RefreshRate = TimeSpan.FromMilliseconds(timeSpan);
            CurrentStartFrame = startFrame;
            CurrentEndFrame = endFrame;
        }

        #endregion

    }
}
